package main

import (
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/hyperledger/fabric-chaincode-go/shim"
	// "gitee.com/yemingzhi/goErrorPaper/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
)

// SimpleAsset implements a simple chaincode to manage an asset
type SimpleAsset struct {
}

type Info struct {
	UserName     string `json:"userName"`
	ID           string `json:"id"`
	Age          int    `json:"age"`
	Email        string `json:"email"`
	RegisterTime string `json:"registerTime"`
}

// Init is called during chaincode instantiation to initialize any
// data. Note that chaincode upgrade also calls this function to reset
// or to migrate data.
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
	// Get the args from the transaction proposal
	args := stub.GetStringArgs()
	if len(args) != 2 {
		return shim.Error("Incorrect arguments. Expecting a key and a value")
	}

	// Set up any variables or assets here by calling stub.PutState()

	// We store the key and the value on the ledger
	err := stub.PutState(args[0], []byte(args[1]))
	if err != nil {
		return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
	}
	return shim.Success(nil)
}

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	fn, args := stub.GetFunctionAndParameters()
	if fn == "set" {
		return t.set(stub, args)
	} else if fn == "get" {
		return t.get(stub, args)
	} else if fn == "addInfo" {
		return t.addInfo(stub, args)
	} else if fn == "getInfo" {
		return t.getInfo(stub, args)
	} else {
		return shim.Error("func is invalid")
	}

	// return shim.Success(nil)
}

func (t *SimpleAsset) set(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	err := stub.PutState(args[0], []byte(args[1]))
	if err != nil {
		return shim.Error("putState failed")
	}
	return shim.Success(nil)
}

func (t *SimpleAsset) get(stub shim.ChaincodeStubInterface, args []string) peer.Response {

	value, err := stub.GetState(args[0])
	if err != nil {
		return shim.Error(fmt.Sprintf("GetState error, err=%s", err))
	}
	if value == nil {
		return shim.Error("get value is empty")
	}
	return shim.Success(value)
}

func (t *SimpleAsset) addInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {

	urlStr := "http://www.baidu.com"
	resp, err := http.Get(urlStr)
	if err != nil {
		fmt.Println(err)
		return shim.Error(fmt.Sprintf("err=%s", err))
	}
	ret, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		log.Printf("request readbody %s err:%v", urlStr, err)
	}
	resp.Body.Close()

	retHash := sha256.Sum256(ret)
	retHashString := string(retHash[:])

	info := Info{
		UserName: "xiaozhang",
		ID:       retHashString,
		Age:      22,
		Email:    "110120119@123.com",
		// RegisterTime: time.Now().Format(time.RFC3339),
	}

	infoJson, err := json.Marshal(info)
	if err != nil {
		return shim.Error(fmt.Sprintf("json Marshal err, err=%s", err))
	}

	err = stub.PutState(args[0], infoJson)
	if err != nil {
		return shim.Error(fmt.Sprintf("stub.PutState err, err=%s", err))
	}

	return shim.Success(nil)
}

func (t *SimpleAsset) getInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	value, err := stub.GetState(args[0])
	if err != nil {
		shim.Error(fmt.Sprintf("GetState failed, err =%s", err))
	}
	if value == nil {
		shim.Error("GetState value is empty")
	}
	// fmt.Println("aaaa", string(value))

	return shim.Success(value)
}

func main() {
	// err := shim.Start(new(SimpleAsset))
	// if err != nil {
	// 	fmt.Printf("Error starting SimpleAsset chaincode,%s", err)
	// }
	if err := shim.Start(new(SimpleAsset)); err != nil {
		fmt.Printf("Error starting SimpleAsset chaincode: %s", err)
	}
}
